using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Admin.NET.Application.Entity.Business;
using Admin.NET.Application.EventBus;
using Admin.NET.Application.Excel;
using Admin.NET.Application.Service.Mp.Dto;
using Admin.NET.Core;
using Furion;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.EventBus;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using Yitter.IdGenerator;

namespace Admin.NET.Application.Service.Mp;

/// <summary>
/// 微信小程序对公支付
/// </summary>
[ApiDescriptionSettings(new string[] { "业务应用" }, Order = 100)]
public class MpCorporate : IDynamicApiController, ITransient, IPrivateDependency
{
	private readonly UserManager _userManager;

	private readonly SqlSugarRepository<CorporatePayment> _rep;

	private readonly SqlSugarRepository<Room> _roomRep;

	private readonly SqlSugarRepository<OwnerNotice> _noticeRep;

	private readonly SqlSugarRepository<RoomBalanceRecord> _balanceRep;

	private readonly RoomService _roomService;

	public MpCorporate(SqlSugarRepository<CorporatePayment> rep, UserManager userManager, SqlSugarRepository<Room> roomRep, SqlSugarRepository<OwnerNotice> noticeRep, SqlSugarRepository<RoomBalanceRecord> balanceRep, RoomService roomService)
	{
		_userManager = userManager;
		_rep = rep;
		_roomRep = roomRep;
		_noticeRep = noticeRep;
		_balanceRep = balanceRep;
		_roomService = roomService;
	}

	/// <summary>
	/// 获取对公的历史记录
	/// </summary>
	/// <param name="page"></param>
	/// <param name="limit"></param>
	/// <param name="roomId"></param>
	/// <returns></returns>
	[HttpGet("/mp/corporatelist")]
	public async Task<dynamic> GetCorporateList(int page, int limit, long? roomId)
	{
		ISugarQueryable<CorporatePayment> queryable = from u in _rep.AsQueryable()
			where u.OwnerId == _userManager.UserId
			select u;
		if (roomId.HasValue)
		{
			queryable = queryable.Where((CorporatePayment u) => (long?)u.RoomId == roomId);
		}
		return await (from u in queryable
			orderby u.CreateTime descending
			select new CorporateOutput
			{
				Id = u.Id,
				Amount = u.Amount,
				AuditRemark = u.AuditRemark,
				AuditUserId = u.AuditUserId,
				AuditUserName = u.AuditUserName,
				OwnerId = u.OwnerId,
				ProofUrl = u.ProofUrl,
				RoomId = u.RoomId,
				Status = u.Status,
				CreateTime = u.CreateTime,
				RoomName = from w in SqlFunc.Subqueryable<Room>()
					where w.Id == u.RoomId
					select w.Name,
				PaymentName = u.PaymentName,
				CustomRoomBillId = u.CustomRoomBillId,
				Bills = u.Bills,
				IsCustomBill = u.IsCustomBill
			}).ToPagedListAsync(page, limit);
	}

	[HttpPost("/mp/corporateExecl")]
	public async Task<IActionResult> ExportCorporate([FromBody] CorporatePageInput input)
	{
		_ = input.roomId;
		string str = "业主信息-" + DateTime.Now.ToString("yyyy-MM-dd");
		List<string> column = new List<string>();
		List<string> title = new List<string>();
		ISugarQueryable<CorporatePayment> queryable = from u in _rep.AsQueryable()
			where u.Status == input.status
			select u;
		if (input.roomId.HasValue)
		{
			queryable = queryable.Where((CorporatePayment u) => (long?)u.RoomId == input.roomId);
		}
		List<CorporateOutput> list = await (from u in queryable
			orderby u.CreateTime descending
			select new CorporateOutput
			{
				Id = u.Id,
				Amount = u.Amount,
				AuditRemark = u.AuditRemark,
				AuditUserId = u.AuditUserId,
				AuditUserName = u.AuditUserName,
				OwnerId = u.OwnerId,
				ProofUrl = u.ProofUrl,
				RoomId = u.RoomId,
				Status = u.Status,
				CreateTime = u.CreateTime,
				RoomName = from w in SqlFunc.Subqueryable<Room>()
					where w.Id == u.RoomId
					select w.Name,
				PaymentName = u.PaymentName,
				CustomRoomBillId = u.CustomRoomBillId,
				Bills = u.Bills,
				IsCustomBill = u.IsCustomBill
			}).ToListAsync();
		column.AddRange(new string[7] { "RoomName", "ProofUrl", "Amount", "Status", "AuditUserName", "AuditRemark", "CreateTime" });
		title.AddRange(new string[7] { "房间", "凭证", "金额(元)", "状态", "审核人", "备注", "提交时间" });
		MemoryStream memery = ExportToExcel.ExportToList(dic: new Dictionary<string, Dictionary<string, string>> { 
		{
			"Status",
			new Dictionary<string, string>
			{
				{ "0", "待审核" },
				{ "1", "审核通过" },
				{ "2", "审核不通过" }
			}
		} }, listInfo: list.ToArray(), headerText: str, sheetName: str, properName: column.ToArray(), titleName: title.ToArray());
		App.HttpContext.Response.ContentType = "application/vnd.ms-excel";
		byte[] aa = memery.ToArray();
		return new FileStreamResult(new MemoryStream(aa), "application/octet-stream")
		{
			FileDownloadName = str + ".xlsx"
		};
	}

	/// <summary>
	/// 提交审核
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/mp/submitcorporate")]
	public async Task SubmitCorporate(CorporateInput input)
	{
		CorporatePayment entity = input.Adapt<CorporatePayment>();
		entity.OwnerId = _userManager.UserId;
		entity.Status = 0;
		if (input.IsCustomBill.GetValueOrDefault() == 1)
		{
			if (input.Bills == null || input.Bills.Count == 0)
			{
				throw Oops.Bah("无效账单，请重新进入页面");
			}
			if (await (from u in _rep.Context.Queryable<CorporatePayment>()
				where u.IsCustomBill == (int?)1 && u.CustomRoomBillId == input.CustomRoomBillId && u.OwnerId == _userManager.UserId && u.RoomId == input.RoomId && u.Status != 2
				select u).CountAsync() > 0)
			{
				throw Oops.Bah("当前账单已在流程中，无需重复提交");
			}
			List<long> billtypes = input.Bills.Select((CustomBillRecord s) => s.BillType).ToList();
			List<BillType> types = await (from w in _rep.Context.Queryable<BillType>()
				where billtypes.Contains(w.Id)
				select w).ToListAsync();
			entity.IsCustomBill = input.IsCustomBill;
			entity.Bills = input.Bills.Select(delegate(CustomBillRecord s)
			{
				BillType billType = types.Where((BillType w) => w.Id == s.BillType).FirstOrDefault();
				return new CustomBillRecord
				{
					BillType = s.BillType,
					Fee = s.Fee,
					Name = billType?.Name,
					IsSupportedInvoicing = billType?.IsSupportedInvoicing
				};
			}).ToList();
			entity.CustomRoomBillId = input.CustomRoomBillId;
			entity.PaymentName = input.PaymentName;
		}
		await _rep.InsertAsync(entity);
	}

	/// <summary>
	/// 获取所有用户的对公记录
	/// </summary>
	/// <param name="page"></param>
	/// <param name="limit"></param>
	/// <param name="roomId"></param>
	/// <param name="status"></param>
	/// <returns></returns>
	[HttpGet("/mp/allcorporate")]
	public async Task<dynamic> GetAllCorporate([FromQuery] CorporatePageInput input)
	{
		ISugarQueryable<CorporatePayment> queryable = from u in _rep.AsQueryable()
			where u.Status == input.status
			select u;
		if (input.roomId.HasValue)
		{
			queryable = queryable.Where((CorporatePayment u) => (long?)u.RoomId == input.roomId);
		}
		return await (from u in queryable
			orderby u.CreateTime descending
			select new CorporateOutput
			{
				Id = u.Id,
				Amount = u.Amount,
				AuditRemark = u.AuditRemark,
				AuditUserId = u.AuditUserId,
				AuditUserName = u.AuditUserName,
				OwnerId = u.OwnerId,
				ProofUrl = u.ProofUrl,
				RoomId = u.RoomId,
				Status = u.Status,
				CreateTime = u.CreateTime,
				RoomName = from w in SqlFunc.Subqueryable<Room>()
					where w.Id == u.RoomId
					select w.Name
			}).ToPagedListAsync(input.Page, input.PageSize);
	}

	/// <summary>
	/// 审核对公支付
	/// </summary>
	/// <param name="input"></param>
	/// <returns></returns>
	[HttpPost("/mp/auditcorporate")]
	public async Task AuditCorporate(AuditCorporateInput input)
	{
		if (input.Status != 1 && input.Status != 2)
		{
			throw Oops.Bah("无效审核");
		}
		try
		{
			await _rep.Context.Ado.BeginTranAsync();
			await _balanceRep.Context.Ado.BeginTranAsync();
			CorporatePayment data = await (from w in _rep.Context.Queryable<CorporatePayment>()
				where w.Id == input.Id
				select w).FirstAsync();
			if (data == null)
			{
				throw Oops.Bah("记录不存在，请刷新后重新尝试");
			}
			if (data.Status > 0)
			{
				throw Oops.Bah("记录已被审核");
			}
			data.Status = input.Status;
			data.AuditRemark = input.AuditRemark;
			data.AuditUserId = _userManager.UserId;
			data.AuditUserName = _userManager.RealName;
			await _rep.Context.Updateable(data).ExecuteCommandAsync();
			Room hasRoom = await (from w in _rep.Context.Queryable<Room>()
				where w.Id == data.RoomId
				select w).FirstAsync();
			if (hasRoom == null && input.Status == 1)
			{
				throw Oops.Bah("房间不存在，无法审核通过");
			}
			if (data.Status == 1)
			{
				PaymentRecord record = new PaymentRecord
				{
					Id = YitIdHelper.NextId(),
					Amount = data.Amount,
					BeforeAmount = hasRoom.Balance,
					BuildingId = hasRoom.BuildingId,
					IsGiveAsAPresent = false,
					CreateUserName = _userManager.RealName,
					IsPay = 1,
					NotifyTime = DateTime.Now,
					OutTradeNo = data.Id.ToString(),
					PayType = PayTypeEnum.对公,
					PaymentName = data.PaymentName,
					OwnerId = data.OwnerId,
					ReceiptAmount = data.Amount,
					RoomId = data.RoomId,
					Subject = data.PaymentName,
					Remark = "对公支付",
					IsCustomBill = data.IsCustomBill,
					Bills = data.Bills,
					CustomRoomBillId = data.CustomRoomBillId
				};
				await _rep.Context.Insertable(record).ExecuteCommandAsync();
				if (data.IsCustomBill.GetValueOrDefault() != 1)
				{
					await (from s in _rep.Context.Updateable<Room>().SetColumns((Room s) => new Room
						{
							Balance = s.Balance + data.Amount
						})
						where s.Id == hasRoom.Id
						select s).ExecuteCommandAsync();
					await _roomService.AddRoomBalanceRecord(_balanceRep.Context, hasRoom.Id, record.Id, 0, record.Amount, _userManager.TenantId, "对公支付充值");
				}
				else
				{
					CustomRoomBill status = await (from s in _rep.Context.Queryable<CustomRoomBill>()
						where (long?)s.Id == data.CustomRoomBillId
						select s).FirstAsync();
					if (status == null)
					{
						throw Oops.Bah("当前自定账单不存在或已删除，无法审核通过");
					}
					if (status.Status == 2)
					{
						throw Oops.Bah("当前自定账单已关闭，无法审核通过");
					}
					IUpdateable<CustomRoomBill> tmp = _rep.Context.Updateable<CustomRoomBill>();
					tmp = tmp.SetColumns((CustomRoomBill s) => s.Status == 2);
					await tmp.Where((CustomRoomBill s) => (long?)s.Id == data.CustomRoomBillId).ExecuteCommandAsync();
				}
			}
			OwnerNotice notice = new OwnerNotice
			{
				OwnerId = data.OwnerId,
				Status = 0,
				Title = ((input.Status == 1) ? "审核通过" : "审核拒绝"),
				TenantId = data.TenantId
			};
			notice.Content = "您房间（" + hasRoom?.Name + "）的对公支付" + notice.Title;
			if (!string.IsNullOrWhiteSpace(input.AuditRemark))
			{
				notice.Content = notice.Content + ";备注：" + input.AuditRemark;
			}
			await _rep.Context.Insertable(notice).ExecuteCommandAsync();
			await _rep.Context.Ado.CommitTranAsync();
			await _balanceRep.Context.Ado.CommitTranAsync();
			if (data.Status == 1)
			{
				try
				{
					EventPayload payload2 = new EventPayload
					{
						Data = data.RoomId.ToString(),
						TenantId = _userManager.TenantId
					};
					await MessageCenter.PublishAsync("SwitchOnGate", payload2);
				}
				catch (Exception)
				{
				}
			}
		}
		catch (Exception ex)
		{
			await _rep.Context.Ado.RollbackTranAsync();
			await _balanceRep.Context.Ado.RollbackTranAsync();
			throw ex;
		}
	}
}
